Repository navigation
Conversation
… DataFrames store_dataframe wrote frames that could be loaded whole but not served a page at a time. The manifest had no per-batch row counts, batches were capped by rows only, and compression could fall back to lz4. - Write pandas and polars frames through one pyarrow IPC path that cuts the record batches itself and records their row counts in the manifest as batch_rows. - Cap batches at about 8 MiB as well as 65,536 rows, sizing them from the average row, and merge small chunks into whole batches. - Compress with zstd, else not at all. - Raise the manifest cap to 64 KiB, and refuse a frame whose manifest would exceed it. - Refuse polars Object columns, nested ones included. Rechunk chunked Categoricals on polars before 1.35.1. Fixes #141 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
|
📦 Python package built successfully!
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #142 +/- ##
==========================================
+ Coverage 78.17% 78.39% +0.21%
==========================================
Files 120 121 +1
Lines 6837 6906 +69
Branches 990 1002 +12
==========================================
+ Hits 5345 5414 +69
Misses 1182 1182
Partials 310 310
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Before 1.43.2, polars' to_arrow() applies the offset of a sliced Array column with nulls twice (pola-rs/polars#28583), so store_dataframe stored shifted values, or a file that aborts pyarrow on read. On those versions, a frame with an Array column at any depth now raises TypeError with an upgrade hint. Struct had the same bug before 1.43.0, but pyarrow rejects that export, so storing fails instead of writing wrong values; Struct frames are not refused. polars older than 1.35.1 is refused outright. That removes the rechunk of chunked Categoricals before 1.35.1, the plain to_arrow() branch before 1.2.1, and the polars.Enum lookup that raised AttributeError on polars older than 0.20. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
|
🚀 Review App Deployment Started
|
Split the polars version, Object and Array checks out of _to_arrow_table, and reword the lz4 note in _select_compression. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
…r own modules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
…ions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
new_file writes nothing; the first bytes reach the file in write_batch. The failing mocks now let the real write_batch write a batch, then raise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
…taframes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
…d polars DataFrames
Batches are cut by the frame's average row size, so long rows that sit together could make one batch several times the 8 MiB target, and the dataframe reader refuses any page that reads more than 32 MiB. A batch over 12 MiB is now split into the longest prefixes that fit. Halving it instead would leave a trail of ever-smaller batches around the long rows, and the reader refuses a page that spans more than 8. Also wraps a test annotation that black rejected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
|
@coderabbitai full review |
✅ Action performed
|
|
No actionable comments were generated in the recent review.
|
Summary
Fixes #141.
store_dataframenow writes Arrow files that the dataframe reader can serve a page at a time. The toolkit cuts the record batches itself, records each batch's row count in the manifest asbatch_rows, caps batches by bytes as well as rows, and compresses with zstd or not at all.Changes
Writing (
_dataframe_storage.py)pa.Table.from_pandas(df, preserve_index=None)for pandas,df.to_arrow(compat_level=oldest)for polars), andpa.ipc.new_filewrites it one batch at a time.clamp(8 MiB / average row bytes, 1, 65,536).nbytes, because every batch writes its own copy of each column and chunk, even ones that share buffers.min(nbytes, get_total_buffer_size()), because the file holds the dictionary once.polars checks (
_polars_compatibility_checks.py, new)Each raises
TypeErrorbefore anything is written:to_arrow()copies a Categorical's whole dictionary into every chunk.to_arrow()exports each value as its memory address.to_arrow()applies a sliced Array's offset twice when the slice holds a null (Exporting a sliced Array column with nulls over the Arrow C interface returns shifted values;pa.table(df)aborts the process pola-rs/polars#28583).Manifest (
_dataframe_storage_manifest.py)batch_rows;rowsis its sum.encode_manifestraisesValueErrorpast the cap, before the current frame is replaced. That takes about 9,000 batches, some 600M rows.dataframes.pystore_dataframedocstring lists the new errors.Behaviour changes
batch_rows, as written by 2.9.0, counts as absent. The next store of that name doesn't keep its file asprevious, and the file is deleted once it is a day old, like any unreferenced frame.ValueErrorfor a frame that needs more batches than the manifest can list. polars Int128 columns raiseArrowInvalidfromto_arrow().to_arrow(), which also copies string views tolarge_string. Storing a 1.4 GiB frame of 10M strings now raises peak memory by 1.47 GiB, up from 0.35 GiB. pandas is unchanged.to_arrow()costs about 0.09 ms per chunk.Known limits
store_dataframeraise pyarrow'sArrowInvalid(a polars bug). The previous frame is kept.Testing
tests/unit/artifacts/cover:batch_rowsmatching the file's record batches;batch_rowsvalidation;🤖 Generated with Claude Code
https://claude.ai/code/session_01VNWoySEbnsryRwTGKUydNx
Summary by CodeRabbit